package com.sharer.last.handler;


import com.sharer.last.annotation.EnumValue;
import com.sharer.last.utils.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;
import java.util.Objects;


/**
 * 自定义枚举校验器
 *
 * @ClassName EnumValueValidator
 * @Author WangJin
 * @Date 2023/05/22/17:06
 * @Description 只支持获取枚举值使用的是`METHOD_NAME`
 * @Version 1.0
 */
@Slf4j
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {

    /**
     * 需要校验的枚举
     */
    private Class<? extends Enum> enumClass;

    /**
     * 枚举获取值的方法名
     */
    private String METHOD_NAME;

    /**
     * 这个方法做一些初始化校验
     *
     * @param constraintAnnotation
     */
    public void initialize(EnumValue constraintAnnotation) {
        enumClass = constraintAnnotation.value();
        METHOD_NAME = constraintAnnotation.methodName();
        try {
            // 先判断该enum是否实现了getCode方法
            enumClass.getDeclaredMethod(METHOD_NAME);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("the enum class has not " + METHOD_NAME + " method", e);
        }
    }

    /**
     * 这个方法写具体的校验逻辑：校验数字是否属于指定枚举类型的范围
     *
     * @param value
     * @param constraintValidatorContext
     * @return
     */
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
        // 如果为空返回 true , 判空用 @NotNull 等专用注解
        if (value == null) {
            return true;
        }
        try {
            // 获取枚举里值的集合
            Enum[] enumConstants = enumClass.getEnumConstants();
            if (enumConstants == null) {
                // 如果不是枚举类型，返回 enumConstants = null
                return true;
            }
            for (Enum e : enumClass.getEnumConstants()) {
                Method declaredMethod = e.getClass().getDeclaredMethod(METHOD_NAME);
                Object obj            = declaredMethod.invoke(e);
                if (Objects.equals(obj, value)) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("校验枚举类型失败， value:{}", JsonUtil.toJson(value));
        }
        return false;
    }
}
